package com.augurit.smartform.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dozer.DozerBeanMapper;
import org.jbpm.api.JbpmException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.augurit.common.entity.SysMetaTable;
import com.augurit.common.system.util.WebContextUtils;
import com.augurit.common.system.web.auth.form.LoginUserForm;
import com.augurit.common.util.lang.StringUtils;
import com.augurit.smartform.constant.FormConstant;
import com.augurit.smartform.constant.PageConstant;
import com.augurit.smartform.constant.TypeConstant;
import com.augurit.smartform.database.DatabaseParser;
import com.augurit.smartform.database.SourceData;
import com.augurit.smartform.database.Table;
import com.augurit.smartform.display.PageElement;
import com.augurit.smartform.display.PageResolve;
import com.augurit.smartform.display.TagElement;
import com.augurit.smartform.service.IFormExecuteService;
import com.augurit.smartform.service.ISmartFormService;
import com.augurit.smartform.service.IWfSupportService;
import com.augurit.wf.bi.convert.WfBusInstanceConvertor;
import com.augurit.wf.bi.service.IWfBusInstanceService;
import com.augurit.wf.bi.service.IWfBusTemplateService;
import com.augurit.wf.bi.service.IWfPageElementService;
import com.augurit.wf.bi.service.IWfTemplateElementRefService;
import com.augurit.wf.bi.web.form.WfBusInstanceForm;
import com.augurit.wf.bi.web.form.WfBusInstanceTaskForm;
import com.augurit.wf.bi.web.form.WfBusTemplateForm;
import com.augurit.wf.bi.web.form.WfPageElementForm;
import com.augurit.wf.common.constant.WfConstant;
import com.augurit.wf.common.dao.Jbpm4TaskDao;
import com.augurit.wf.common.entity.Jbpm4Task;
import com.augurit.wf.common.entity.WfTemplateElementRef;
import com.augurit.wf.common.service.IWfService;
import com.augurit.wf.common.util.WfUtils;
import com.augurit.wf.mgmt.convert.Jbpm4TaskConvertor;

@Service
@Transactional
public class WfSupportService implements IWfSupportService {

	@Autowired
	private PageResolve pageResolve;
	@Autowired
	private DatabaseParser databaseParser;
	@Autowired
	private IWfPageElementService wfPageElementService;
	@Autowired
	private IWfTemplateElementRefService wfTemplateElementRefService;
	@Autowired
	private IWfBusTemplateService wfBusTemplateService;
	@Autowired
	private IFormExecuteService formExecuteService;
	@Autowired
	private IWfService wfService;
	@Autowired
	private ISmartFormService smartFormService;
	@Autowired
	private Jbpm4TaskDao jbpm4TaskDao;
	@Autowired
	private IWfBusInstanceService wfBusInstanceService;
	@Autowired
	private DozerBeanMapper dozer;

	/**
	 * 执行工作流相关操作，包括向页面元素表插入相关值
	 * 
	 * @param source
	 *            cuigeqiang
	 */
	public void saveElementAndRef(SourceData source) {
		String templateId = source.getTemplateId();
		String xmlStr = source.getXml();
		if (StringUtils.isNotBlank(templateId)) {
			if (this.checkWfRelation(xmlStr)) {
				PageElement page = pageResolve.paser(xmlStr);
				this.saveWfCommonElementRef(source);
				this.saveTagElement(page, source);

				if (StringUtils.isNotBlank(page.getName())) {
					SysMetaTable smForm = smartFormService
							.getLastedSmFormByName(page.getName().toUpperCase());
					if (smForm != null) {
						String sourceXmlStr = smForm.getRawXml();
						List<Table> tables = databaseParser
								.parseToAscTables(sourceXmlStr);
						if (tables != null && tables.size() > 0) {
							this.updateBusTemplate(source, tables);
						}
					}
				}
			}
		}
	}

	/**
	 * 点击暂存按钮执行操作
	 * 
	 * @param request
	 * @return cuigeqiang
	 */
	@SuppressWarnings("unchecked")
	public WfBusInstanceTaskForm wfBusSave(HttpServletRequest request) {

		String id = request.getParameter("id");

		// ===============城管委修改开始（针对于预受理案件）===================
		String ysl = "";
		Map parameterMap = request.getParameterMap();
		if (parameterMap.containsKey("SR_DLZYSQB_YSL"))
			ysl = request.getParameter("SR_DLZYSQB_YSL"); // 道路占用中的预受理
		else if (parameterMap.containsKey("SR_DLWJSQB_YSL"))
			ysl = request.getParameter("SR_DLWJSQB_YSL"); // 道路挖掘中的是否预受理
		else if (parameterMap.containsKey("SS_CCGBSQB_YSL"))
			ysl = request.getParameter("SS_CCGBSQB_YSL"); //公共厕所拆除、关闭审批中的预受理
		else if (parameterMap.containsKey("shlj_cz_ysl"))
			ysl = request.getParameter("shlj_cz_ysl"); //城市生活垃圾的处置
		else if (parameterMap.containsKey("hw_shljqs_ysl"))
			ysl = request.getParameter("hw_shljqs_ysl"); //陆域生活垃圾
		else if (parameterMap.containsKey("syshlj_ysl"))
			ysl = request.getParameter("syshlj_ysl"); //水域生活垃圾
		else
			ysl = request.getParameter("ysl");
		// =============城管委修改结束======================

		String templateCode = request.getParameter("templateCode");
		String taskInstDbid = request.getParameter("taskInstDbid");
		LoginUserForm loginUser = (LoginUserForm) request.getSession()
				.getAttribute(WebContextUtils.SES_LOGIN_USER);

		if (StringUtils.isNotBlank(templateCode) && loginUser != null) {

			// 保存业务处理
			Map<String, Object> map = this.saveCurrentForm(request);

			// 业务校验
			if (map == null || map.get("ID") == null)
				throw new JbpmException("错误原因：主业务实体主键为空！");

			// 流程变量处理
			Map<String, Object> params = new HashMap<String, Object>();

			params.put(WfConstant.VAR_SMARTFORM_ID, map.get("ID"));
			params.put(WfConstant.VAR_SMARTFORM_USER, loginUser.getUser());

			WfBusTemplateForm template = wfBusTemplateService
					.getByTemplateCode(templateCode);
			params.put(WfConstant.VAR_SMARTFORM_TEMPLATE, template);

			if (taskInstDbid != null && taskInstDbid.trim().length() > 0) {
				Jbpm4Task task = jbpm4TaskDao.get(Long.valueOf(taskInstDbid));
				if (task != null) {
					params.put(WfConstant.VAR_SMARTFORM_TASK,
							Jbpm4TaskConvertor.convertToForm(task));
				}
			}

			// 流程处理
			if (StringUtils.isBlank(id) || "1".equals(ysl)) {
				return wfService.wfBusStart(template, map, loginUser.getUser()
						.getLoginName(), params);
			} else {
				if (taskInstDbid == null || taskInstDbid.trim().length() == 0)
					throw new JbpmException("错误原因：任务主键为空！");

				// 同步汇总字段
				WfBusInstanceForm inst = WfBusInstanceConvertor
						.convertVoToForm(wfBusInstanceService
								.getByMasterEntityAndKey(template
										.getMasterEntity(), map.get("ID")
										.toString()));
				WfUtils.syncSummary(map, inst, dozer);
				wfBusInstanceService.save(inst);

				wfService.getProcessEngine().getTaskService().setVariables(
						taskInstDbid.toString(), params); // 同步流程变量
				return WfUtils.getCurTaskInfo(map.get("ID").toString(), Long
						.valueOf(taskInstDbid));
			}
		}

		return null;
	}

	/**
	 * 检查是否工作流相关表单
	 * 
	 * @param sourceXmlStr
	 * @return cuigeqiang
	 */
	public boolean checkWfRelation(String sourceXmlStr) {
		boolean wfRelation = false;
		try {
			Document document = DocumentHelper.parseText(sourceXmlStr);
			List<Element> elements = document.selectNodes("//object");
			for (Element element : elements) {
				String formTypeStr = element.attributeValue("formType");
				if (StringUtils.isNotBlank(formTypeStr)
						&& FormConstant.WORKFLOW.equalsIgnoreCase(formTypeStr)) {
					wfRelation = true;
					break;
				} else if (StringUtils.isNotBlank(formTypeStr)
						&& FormConstant.OA.equalsIgnoreCase(formTypeStr)) {
					wfRelation = true;
					break;
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return wfRelation;
	}

	/**
	 * 保存页面元素以及页面元素
	 * 
	 * @param page
	 *            cuigeqiang
	 */
	private void saveTagElement(PageElement page, SourceData source) {
		String pageCode = page.getPageCode();
		Long templateId = Long.parseLong(source.getTemplateId());
		String elementCode = pageCode + PageConstant.FORM_SUFFIX;
		WfPageElementForm form = wfPageElementService
				.getByElementCode(elementCode);
		if (form == null) {
			// 加入表单元素
			int elementSortNo = 0;
			if (this.existFormElementForTemplate(templateId)) {
				elementSortNo = 1;
			}
			form = new WfPageElementForm();
			form.setElementCode(elementCode);
			form.setElementType(WfPageElementForm.FORM_ELEM_TYPE);
			form.setElementName(page.getCnName());
			form.setIsPublic(WfPageElementForm.NOT_PUBLIC);
			form.setIsActive(WfPageElementForm.ACTIVE);
			form.setElementInvokeMode(WfPageElementForm.INVOKE_MODE_IFRAME);
			form.setElementInvoke(PageConstant.PREFIX_PAGE_PATH + pageCode);
			form.setElementSortNo(elementSortNo);
			wfPageElementService.save(form);
			this.saveTemplateElementRef(form, templateId);

			// 加入标签元素
			Iterator<TagElement> tags = page.getElements().values().iterator();
			while (tags.hasNext()) {
				TagElement tag = tags.next();
				if (TypeConstant.WF_BUTTON.equals(tag.getType())) {
					WfPageElementForm oldElement = wfPageElementService
							.getByElementCode(tag.getId());
					if (oldElement != null) {
						oldElement.setElementName(tag.getTitle());
						wfPageElementService.save(oldElement);
					} else {
						oldElement = new WfPageElementForm();
						oldElement.setElementCode(tag.getId());
						oldElement
								.setElementType(WfPageElementForm.BUTTON_ELEM_TYPE);
						oldElement.setElementName(tag.getTitle());
						oldElement.setIsPublic(WfPageElementForm.NOT_PUBLIC);
						oldElement.setIsActive(WfPageElementForm.ACTIVE);
						wfPageElementService.save(oldElement);
						this.saveTemplateElementRef(oldElement, templateId);
					}
				} else {
					WfPageElementForm oldElement = wfPageElementService
							.getByElementCode(tag.getId());
					if (oldElement != null) {
						oldElement.setElementName(tag.getTitle());
						wfPageElementService.save(oldElement);
					} else {
						oldElement = new WfPageElementForm();
						oldElement.setElementCode(tag.getId());
						oldElement
								.setElementType(WfPageElementForm.FIELD_ELEM_TYPE);
						oldElement.setElementName(tag.getTitle());
						oldElement.setIsPublic(WfPageElementForm.NOT_PUBLIC);
						oldElement.setIsActive(WfPageElementForm.ACTIVE);
						wfPageElementService.save(oldElement);
						this.saveTemplateElementRef(oldElement, templateId);
					}
				}
			}
		} else {// 更新
			form.setElementName(page.getCnName());
			wfPageElementService.save(form);

			// 加入标签元素
			Iterator<TagElement> tags = page.getElements().values().iterator();
			while (tags.hasNext()) {
				TagElement tag = tags.next();
				if (TypeConstant.WF_BUTTON.equals(tag.getType())) {
					WfPageElementForm oldElement = wfPageElementService
							.getByElementCode(tag.getId());
					if (oldElement != null) {
						oldElement.setElementName(tag.getTitle());
						wfPageElementService.save(oldElement);
					} else {
						oldElement = new WfPageElementForm();
						oldElement.setElementCode(tag.getId());
						oldElement
								.setElementType(WfPageElementForm.BUTTON_ELEM_TYPE);
						oldElement.setElementName(tag.getTitle());
						oldElement.setIsPublic(WfPageElementForm.NOT_PUBLIC);
						oldElement.setIsActive(WfPageElementForm.ACTIVE);
						wfPageElementService.save(oldElement);
						this.saveTemplateElementRef(oldElement, templateId);
					}
				} else {
					WfPageElementForm oldElement = wfPageElementService
							.getByElementCode(tag.getId());
					if (oldElement != null) {
						oldElement.setElementName(tag.getTitle());
						wfPageElementService.save(oldElement);
					} else {
						oldElement = new WfPageElementForm();
						oldElement.setElementCode(tag.getId());
						oldElement
								.setElementType(WfPageElementForm.FIELD_ELEM_TYPE);
						oldElement.setElementName(tag.getTitle());
						oldElement.setIsPublic(WfPageElementForm.NOT_PUBLIC);
						oldElement.setIsActive(WfPageElementForm.ACTIVE);
						wfPageElementService.save(oldElement);
						this.saveTemplateElementRef(oldElement, templateId);
					}
				}
			}
		}
	}

	/**
	 * 判断某个模板是否已经存在表单元素
	 * 
	 * @param templateId
	 * @return cuigeqiang
	 */
	private boolean existFormElementForTemplate(Long templateId) {
		boolean exist = false;
		List<WfPageElementForm> elements = wfBusTemplateService
				.getElementsByType(templateId,
						WfPageElementForm.FORM_ELEM_TYPE, false);
		if (elements != null && elements.size() > 0) {
			exist = true;
		}
		return exist;
	}

	/**
	 * 保存流程共用的TOOLBAR和BUTTON
	 * 
	 * @param source
	 *            cuigeqiang
	 */
	private void saveWfCommonElementRef(SourceData source) {
		Long templateId = Long.parseLong(source.getTemplateId());
		WfPageElementForm pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_TOOLBAR);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_HISTORY);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_OPINION);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_SAVE_IFRAME);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_SEND);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_VIEW_PROC_DIAG);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_DOWNLOAD);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_ATTACH_REFRESH);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_UPLOAD_ATTACH);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
		pageElementForm = wfPageElementService
				.getByElementCode(PageConstant.WF_DELETE_FILE);
		if (pageElementForm != null) {
			this.saveTemplateElementRef(pageElementForm, templateId);
		}
	}

	/**
	 * 保存模板和页面元素关联
	 * 
	 * @param pageElementForm
	 * @param templateId
	 *            cuigeqiang
	 */
	private void saveTemplateElementRef(WfPageElementForm pageElementForm,
			Long templateId) {
		WfTemplateElementRef wfElementRef = wfTemplateElementRefService.get(
				templateId, pageElementForm.getId());
		if (wfElementRef == null) {
			pageElementForm.setTemplateId(templateId);
			wfPageElementService.addPageElement(pageElementForm);
		}
	}

	/**
	 * 更新BUSTEMPLATE cuigeqiang
	 */
	private void updateBusTemplate(SourceData data, List<Table> tables) {
		if (StringUtils.isNotBlank(data.getTemplateId())) {
			Long templateId = Long.parseLong(data.getTemplateId());
			WfBusTemplateForm templateForm = wfBusTemplateService
					.get(templateId);

			String oldMasterEntity = templateForm.getMasterEntity();
			List<String> slaveEntityList = new ArrayList<String>();
			String oldSlaveEntities = templateForm.getSlaveEntities();
			String[] oldSlaveEntitiesArray = new String[] {};
			if (StringUtils.isNotBlank(oldSlaveEntities)) {
				oldSlaveEntitiesArray = oldSlaveEntities
						.split(PageConstant.COMMA_SEPERATOR);
			}
			for (String oldSlaveEntity : oldSlaveEntitiesArray) {
				slaveEntityList.add(oldSlaveEntity);
			}

			for (int i = 0; i < tables.size(); i++) {
				Table table = tables.get(i);
				if (i == 0) {
					if (StringUtils.isBlank(oldMasterEntity)) {
						templateForm.setMasterEntity(table.getFullName());
					} else {
						if (!oldMasterEntity.equalsIgnoreCase(table
								.getFullName())
								&& !this.containStr(slaveEntityList, table
										.getFullName())) {
							slaveEntityList.add(table.getFullName());
						}
					}
				} else {
					if (!this.containStr(slaveEntityList, table.getFullName())) {
						slaveEntityList.add(table.getFullName());
					}
				}
			}

			templateForm.setSlaveEntities(StringUtils
					.convertStringListToString(slaveEntityList,
							PageConstant.COMMA_SEPERATOR));
			wfBusTemplateService.save(templateForm);
		}
	}

	/**
	 * 保存业务数据
	 * 
	 * @param request
	 *            cuigeqiang
	 */
	private Map<String, Object> saveCurrentForm(HttpServletRequest request) {
		Map<String, Object> summaryMap = new LinkedHashMap<String, Object>();
		Long newId = null;
		List<Long> ids = formExecuteService.updateForm(request);
		if (ids != null && ids.size() > 0) {
			newId = ids.get(0);
		}
		String pageCode = request.getParameter(PageConstant.KEY_PAGE_CODE);
		summaryMap.put("ID", newId);
		if (StringUtils.isNotBlank(pageCode) && newId != null) {
			formExecuteService.loadSummaryDataByPageCodeAndId(summaryMap, newId
					.toString(), pageCode);
		}
		return summaryMap;
	}

	/**
	 * 判断字符串数组是否包含字符串
	 * 
	 * @param strArray
	 * @param str
	 * @return cuigeqiang
	 */
	private boolean containStr(List<String> strList, String str) {
		boolean flag = false;
		if (str != null && strList != null && strList.size() > 0) {
			for (String innerStr : strList) {
				if (str.equalsIgnoreCase(innerStr)) {
					flag = true;
					break;
				}
			}
		}
		return flag;
	}
}
